package com.jy.oms.framework.asyn.task.cluster.model;

import com.jy.oms.framework.asyn.task.model.TaskGroup;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 逻辑工作节点
 *
 * @author liuquan
 */
public class WorkNode {

    /**
     * 真实节点，目前是1:1关系
     */
    private RealWorkNode realWorkNode;

    /**
     * 节点工作模式
     */
    private WorkModeEnum workModel = WorkModeEnum.SHARE;

    /**
     * 指定执行特定的任务组
     */
    private List<WorkNodeExecutableTask> executableGroupTasks;

    /**
     * 指定执行特定的任务
     */
    private List<WorkNodeExecutableTask> executableTasks;

    /**
     * 合并后可执行的任务组、任务
     */
    private List<WorkNodeExecutableTask> mergedExecutableTasks;

    private Map<Integer, WorkNode> otherClusterWorkNodes = new ConcurrentHashMap<>();

    public static WorkNode create() {
        return new WorkNode();
    }

    public void mergeWorkNodeExecutableTask() {
        Map<String, WorkNodeExecutableTask> taskMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(executableTasks)) {
            for (WorkNodeExecutableTask task : executableTasks) {
                taskMap.put(task.getTaskGroup(), task);
            }
        }

        if (CollectionUtils.isNotEmpty(executableGroupTasks)) {
            for (WorkNodeExecutableTask groupTask : executableGroupTasks) {
                if (taskMap.get(groupTask.getTaskGroup()) == null) {
                    taskMap.put(groupTask.getTaskGroup(), groupTask);
                }
            }
        }

        mergedExecutableTasks = taskMap.values().stream().collect(Collectors.toList());
        workModel = CollectionUtils.isEmpty(mergedExecutableTasks) ? WorkModeEnum.SHARE : WorkModeEnum.EXCLUSIVE;
    }

    public Pair<Boolean, WorkNodeExecutableTask> ableCollectShareTask(TaskGroup taskGroup) {
        Map<Integer, WorkNode> otherClusterWorkNodes = this.getOtherClusterWorkNodes();
        if (MapUtils.isEmpty(otherClusterWorkNodes)) {
            return Pair.of(true, null);
        }

        for (Map.Entry<Integer, WorkNode> entry : otherClusterWorkNodes.entrySet()) {
            if (CollectionUtils.isEmpty(entry.getValue().getMergedExecutableTasks())) {
                continue;
            }

            for (WorkNodeExecutableTask executableTask : entry.getValue().getMergedExecutableTasks()) {
                if (executableTask.getTaskGroup().equals(taskGroup.getGroup())) {
                    return Pair.of(false, executableTask);
                }
            }
        }

        return Pair.of(true, null);
    }

    public RealWorkNode getRealWorkNode() {
        return realWorkNode;
    }

    public WorkNode setRealWorkNode(RealWorkNode realWorkNode) {
        this.realWorkNode = realWorkNode;
        return this;
    }

    public WorkModeEnum getWorkModel() {
        return workModel;
    }

    public WorkNode setWorkModel(WorkModeEnum workModel) {
        this.workModel = workModel;
        return this;
    }

    public List<WorkNodeExecutableTask> getExecutableTasks() {
        return executableTasks;
    }

    public WorkNode setExecutableTasks(List<WorkNodeExecutableTask> executableTasks) {
        this.executableTasks = executableTasks;
        return this;
    }

    public List<WorkNodeExecutableTask> getExecutableGroupTasks() {
        return executableGroupTasks;
    }

    public WorkNode setExecutableGroupTasks(List<WorkNodeExecutableTask> executableGroupTasks) {
        this.executableGroupTasks = executableGroupTasks;
        return this;
    }

    public List<WorkNodeExecutableTask> getMergedExecutableTasks() {
        return mergedExecutableTasks;
    }

    public Map<Integer, WorkNode> getOtherClusterWorkNodes() {
        return otherClusterWorkNodes;
    }

    public WorkNode setOtherClusterWorkNodes(Map<Integer, WorkNode> otherClusterWorkNodes) {
        this.otherClusterWorkNodes = otherClusterWorkNodes;
        return this;
    }
}
